//
//  GameObject.h
//  Components
//
//  Created by Jeppe Nielsen on 3/6/12.
//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//

#pragma once//;
#include "IGameComponent.hpp"
#include <vector>
#include "Event.hpp"

namespace Typhoon {
	class Aspect;
    class GameObject {
    public:
        
        GameObject();
        ~GameObject();
        
        template<class T>
        T* AddComponent();
        
        template<class T>
        void RemoveComponent();
        
        template<class T>
        T* GetComponent() const;
		
		Event<GameObject*> ComponentAdded;
		Event<GameObject*> ComponentRemoved;

		Event<GameObject*> RemovedFromWorld;

		bool SatisfyAspect(const Aspect& aspect) const;

		void* Data;
        
    private:
        
        typedef std::vector<IGameComponent*> Components;
        Components components;
        int componentsCount;
        
    };
}


template<class T>
T* Typhoon::GameObject::AddComponent() {
    T* component = new T();
	component->gameObject = this;
    const unsigned int index = T::GetIndex();
    if (index>=componentsCount) {
        for (int i = componentsCount; i<=index;i++) {
            components.push_back(0);
        }
        componentsCount = index + 1;
    }
    else if (components[index]) {
        //Component already added
        return 0;
    }
    components[index]=component;
	ComponentAdded(this);
    return component;
}

template<class T>
void Typhoon::GameObject::RemoveComponent() {
    const unsigned int index = T::GetIndex();
    if (index>=componentsCount) return;
    T* component = (T*)components[index];
    if (!component) {
        //Component doesn't exists
        return;
    }
    delete component;
    components[index] = 0;
	ComponentRemoved(this);
}

template<class T>
T* Typhoon::GameObject::GetComponent() const {
    const unsigned int index = T::GetIndex();
    if (index>=componentsCount) return 0;
    return (T*)components[index];
}